package com.ys.service.business.impl;

import java.io.*;
import java.lang.reflect.Field;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import com.amazonaws.services.lambda.model.ServiceException;
import com.ys.config.MyConfig;
import com.ys.entity.base.TbFileInfoBatchDownload;
import com.ys.util.DateUtil;
import com.ys.util.dhecp.DateUtils;
import com.ys.util.upload.UploadUtilYs;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.ys.entity.base.TbFileInfo;
import com.ys.entity.sys.TsUserChange;
import com.ys.enume.base.TbFileInfoEnum;
import com.ys.mapper.base.BaseDiyMapper;
import com.ys.mapper.base.TbFileInfoMapper;
import com.ys.service.business.TbFileInfoService;
import com.ys.util.shiro.ShiroUtils;
import com.ys.vo.R;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import static org.ehcache.config.ResourceType.Core.DISK;

@Service("tbFileInfoService")
public class TbFileInfoServiceImpl implements TbFileInfoService {
	private static final Logger logger = LoggerFactory.getLogger(TbFileInfoServiceImpl.class);
	@Autowired
	private BaseDiyMapper baseDiyMapper;
	@Autowired
	private TbFileInfoMapper tbFileInfoMapper;
	
	@Override
	@Transactional
	public R add(TbFileInfo entity) throws Exception {
		
		String loginUserId = ShiroUtils.getUserId();
		TsUserChange tsUserChange = new TsUserChange().setUserId(loginUserId).setStatus(1).queryFirst();
		entity.setCreateChangeId(tsUserChange.getId());
		entity.setStatus(1);
		tbFileInfoMapper.insert(entity);
		
		// 统计数量
		Integer num = new TbFileInfo()
				.setSourceCode(entity.getSourceCode())
				.setSourceId(entity.getSourceId())
				.setSourceType(entity.getSourceType())
				.setStatus(1)
				.count();
		
		// 更新相应的表字段值
		String tableName = TbFileInfoEnum.SourceType.getTableName(entity.getSourceType());
		String fieldName = entity.getSourceCode();
		Long sourceId = entity.getSourceId();
		baseDiyMapper.updateMultyFileCol(tableName, fieldName, sourceId, num);
		return R.ok(num);
	}
	
	@Override
	@Transactional
	public R edit(Map<String, Object> params) throws Exception {
		TbFileInfo entity = JSON.parseObject(JSON.toJSONString(params), TbFileInfo.class);

		tbFileInfoMapper.update(entity);
		
		return R.ok("操作成功");
	}

	@Override
	public R deleteFalse(Long id) {
		if (id == null) {
			return R.error("ID不能为空");
		}
		
		TbFileInfo entity = new TbFileInfo().setId(id).queryFirst();
		entity.setStatus(0);
		tbFileInfoMapper.update(entity);
		
		// 统计数量
		Integer num = new TbFileInfo()
				.setSourceCode(entity.getSourceCode())
				.setSourceId(entity.getSourceId())
				.setSourceType(entity.getSourceType())
				.setStatus(1)
				.count();
		
		// 更新相应的表字段值
		String tableName = TbFileInfoEnum.SourceType.getTableName(entity.getSourceType());
		String fieldName = entity.getSourceCode();
		Long sourceId = entity.getSourceId();
		baseDiyMapper.updateMultyFileCol(tableName, fieldName, sourceId, num);
		
		return R.ok(num);
	}






	/**
	 * 批量下载文件(生成zip文件下载)(注意，一次请求只能调用一次，无法调用多次)
	 *
	 * @param list     要下载的批量文件集合
	 * @param request  request
	 * @param response response
	 * @param zipFileName    压缩包文件名字
	 */
	@Override
	public void downLoadFileBatch(List<TbFileInfo> list, HttpServletRequest request, HttpServletResponse response,String zipFileName) throws Exception{
		//设置响应头信息
		response.reset();
		response.setCharacterEncoding("utf-8");
		//response.setContentType("multipart/form-data");
		//设置压缩包的名字
		String downloadName = zipFileName + ".zip";
		//返回客户端浏览器的版本号、类型
		String agent = request.getHeader("USER-AGENT");
		//针对IE或者以IE为内核的浏览器：
		if (agent.contains("MSIE") || agent.contains("Trident")) {
			downloadName = java.net.URLEncoder.encode(downloadName, "UTF-8");
		} else {
			//非IE浏览器的处理：
			downloadName = new String(downloadName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
		}
		response.setHeader("Content-Disposition", "attachment;fileName=\"" + downloadName + "\"");

		//设置压缩流：直接写入response，实现边压缩边下载
		ZipOutputStream zipOs = null;
		//循环将文件写入压缩流
		DataOutputStream os = null;
		//文件
		//File file;
		try {
			list = isRepeatFile(list);
			zipOs = new ZipOutputStream(new BufferedOutputStream(response.getOutputStream()));
			//设置压缩方法
			zipOs.setMethod(ZipOutputStream.DEFLATED);
			//遍历文件信息（主要获取文件名/文件路径等）
			for (TbFileInfo entity : list) {
				//文件名（包含后缀名,如:测试.pdf）
				String name = entity.getPreName();
				//文件路径
				URL url = new URL(entity.getFilePath());
				URLConnection connection = url.openConnection();
				int status =  ((HttpURLConnection) connection).getResponseCode();
				if(status != 200){
					throw new ServiceException("文件不存在");
				}
				InputStream is = connection.getInputStream();
				//添加ZipEntry，并将ZipEntry写入文件流
				zipOs.putNextEntry(new ZipEntry("folderName/"+name));
				os = new DataOutputStream(zipOs);
				byte[] b = new byte[100];
				int length;
				//读入需要下载的文件的内容，打包到zip文件
				while ((length = is.read(b)) != -1) {
					os.write(b, 0, length);
				}
				//关闭流
				is.close();
				zipOs.closeEntry();
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			//关闭流
			if (os != null) {
				os.flush();
				os.close();
			}
			if (zipOs != null) {
				zipOs.close();
			}
		}

	}



	/**
	 * 批量下载文件(生成zip文件下载)，并进行文件夹划分（只划分一个文件夹层级，生成路径示例：zipFileName/folderName/文件）(注意，一次请求只能调用一次，无法调用多次)
	 *
	 * @param list     要下载的批量文件集合（划分好之后的）
	 * @param request  request
	 * @param response response
	 * @param zipFileName    压缩包文件名字
	 */
	@Override
	public void downLoadFileBatchWithFolder(List<TbFileInfoBatchDownload> list, HttpServletRequest request, HttpServletResponse response, String zipFileName)throws Exception{
		//设置响应头信息
		response.reset();
		response.setCharacterEncoding("utf-8");
		//response.setContentType("multipart/form-data");
		//设置压缩包的名字
		String downloadName = zipFileName + ".zip";
		//返回客户端浏览器的版本号、类型
		String agent = request.getHeader("USER-AGENT");
		//针对IE或者以IE为内核的浏览器：
		if (agent.contains("MSIE") || agent.contains("Trident")) {
			downloadName = java.net.URLEncoder.encode(downloadName, "UTF-8");
		} else {
			//非IE浏览器的处理：
			downloadName = new String(downloadName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
		}
		response.setHeader("Content-Disposition", "attachment;fileName=\"" + downloadName + "\"");

		//设置压缩流：直接写入response，实现边压缩边下载
		ZipOutputStream zipOs = null;
		//循环将文件写入压缩流
		DataOutputStream os = null;
		//文件
		//File file;
		try {

			zipOs = new ZipOutputStream(new BufferedOutputStream(response.getOutputStream()));
			//设置压缩方法
			zipOs.setMethod(ZipOutputStream.DEFLATED);

			for (TbFileInfoBatchDownload folderItem : list) {
				String folderName = folderItem.getFolderName()!=null && !"".equals(folderItem.getFolderName()) ? folderItem.getFolderName()+"/":zipFileName+"/";
				List<TbFileInfo> fileList = isRepeatFile(folderItem.getFileList());
				//遍历文件信息（主要获取文件名/文件路径等）
				for (TbFileInfo entity : fileList) {
					//文件名（包含后缀名,如:测试.pdf）
					String name = entity.getPreName();
					//文件路径
					URL url = new URL(entity.getFilePath());
					URLConnection connection = url.openConnection();
					int status =  ((HttpURLConnection) connection).getResponseCode();
					if(status != 200){
						throw new ServiceException("文件不存在");
					}
					InputStream is = connection.getInputStream();
					//添加ZipEntry，并将ZipEntry写入文件流
					zipOs.putNextEntry(new ZipEntry(folderName+name));
					os = new DataOutputStream(zipOs);
					byte[] b = new byte[100];
					int length;
					//读入需要下载的文件的内容，打包到zip文件
					while ((length = is.read(b)) != -1) {
						os.write(b, 0, length);
					}
					//关闭流
					is.close();
					zipOs.closeEntry();
				}
			}


		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			//关闭流
			if (os != null) {
				os.flush();
				os.close();
			}
			if (zipOs != null) {
				zipOs.close();
			}
		}
	}






	/**
	 * 判断fileName是否重复，重复则以fileName+序号来重命名
	 * @param list
	 * @return
	 */
	public List<TbFileInfo> isRepeatFile(List<TbFileInfo> list) {
		Map<String, Integer> fileNameCountMap = new HashMap<>();
		for (TbFileInfo entity : list) {
			String fileName = entity.getPreName()+"."+entity.getSufName();
			String[] split = fileName.split("\\.");
			String name = split[0];
			String extension = split.length > 1 ? split[1] : ""; // 处理没有扩展名的情况
			// 如果文件名已经存在，则进行重命名
			if (fileNameCountMap.containsKey(fileName)) {
				int count = fileNameCountMap.get(fileName);
				String newFileName = String.format("%s_(%d).%s", name, count, extension);
				entity.setPreName(newFileName);
				// 更新文件名计数
				fileNameCountMap.put(fileName, count + 1);
			} else {
				entity.setPreName(fileName);
				// 文件名首次出现，记录计数为1
				fileNameCountMap.put(fileName, 1);
			}
		}
		return list;
	}





}
